#include <locale.h>
#include <time.h>
#include <stddef.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <SDL.h>
#include <SDL_ttf.h>
#include "hi_common.h"
#include "hi_comm_vpss.h"
#include "hi_comm_video.h"
#include "hi_comm_region.h"
#include "mpi_region.h"
#include "loadbmp.h"
#include "enc_shrm.h"
#include "enc_common.h"
#include "hi_type.h"
#include "loadbmp.h"
#include "enc_osd.h"
#include "ximage.h"
#include <time.h>
#include "enc_osd_mgr.h"

extern _enc_main_data main_data;
static pENC_DEVSET_SLAVE g_encset_slv_osd = NULL;
//static enc_osd_sub 		osd_sub;
//static enc_osd_pic 		osd_pic;
//static enc_osd_pic 		osd_qr;
//static const char *font_bmp	= "font.bmp";
//static const char *font_show	= "ximage.bmp";
static HiOSDMgr* g_pOsdMgr = NULL;


void enc_osd_destory(HI_S32 chn, RGN_HANDLE handle)
{
	MPP_CHN_S chn_s;
	chn_s.enModId = HI_ID_VENC;
	chn_s.s32ChnId = chn; 			// hcc 通道号暂时设置为1
	chn_s.s32DevId = 0; 	
	
	// 将区域从通道中分离
	HI_MPI_RGN_DetachFromChn(handle, &chn_s);
	HI_MPI_RGN_Destroy(handle);	
}

// hcc 完成OSD部分的通道和句柄销毁
void enc_osd_all_destory(void)
{
	MPP_CHN_S chn_s;
	int i, j;
	
	for(i = ENC_MAX_CHL - 1; i >= 0; i--)
	{
		chn_s.enModId = HI_ID_VENC;
		chn_s.s32ChnId = i;	
		chn_s.s32DevId = 0;

		// 销毁句柄
		for (j = ENC_OSD_MAX_HANDLE + 10; j >= 0; j--)	// rand(10)
		{
			HI_MPI_RGN_DetachFromChn(j, &chn_s);
			HI_MPI_RGN_Destroy(j);	
		}	
	}	
}

// 获取字幕的长宽，便于创建线程进行滚动显示
SDL_Surface* enc_osd_get_size(SDL_Surface *surface, void *p_this, enc_osd_sub *osd_sub)
{
	EncHiOSD *p_run = (EncHiOSD *)p_this;
	SDL_PixelFormat *fmt;
	SDL_Surface 	*text;
	stENC_OSDSET *p_osd_set = &p_run->osd_set;
	
	SDL_Color fgcolor;
	SDL_Color bgcolor;
	fgcolor.r = RGB_R(p_osd_set->osd_cfg.osd_sub.sub_fontcolor);
	fgcolor.g = RGB_G(p_osd_set->osd_cfg.osd_sub.sub_fontcolor);
	fgcolor.b = RGB_B(p_osd_set->osd_cfg.osd_sub.sub_fontcolor);

	bgcolor.r = RGB_R(p_osd_set->osd_cfg.osd_sub.sub_backcolor);
	bgcolor.g = RGB_G(p_osd_set->osd_cfg.osd_sub.sub_backcolor);
	bgcolor.b = RGB_B(p_osd_set->osd_cfg.osd_sub.sub_backcolor);

	fmt = (SDL_PixelFormat*)malloc(sizeof(SDL_PixelFormat));
	if (NULL == fmt)
	{
		printf("malloc SDL_PixelFormat *fmt error\n");
		return NULL;
	}
	memset(fmt, 0, sizeof(SDL_PixelFormat));	
	
	text = TTF_RenderUTF8_Shaded(osd_sub->p_sub_font, (char *)osd_sub->sub_content, fgcolor, bgcolor);
	
	if (NULL == text)
	{
		SDL_FreeSurface(text); 
		printf("SDL_Surface get text bmp error\n");
		return NULL;
	}
	
	fmt->BitsPerPixel = 16;    
	fmt->BytesPerPixel = 2;    
	fmt->colorkey = 0xffffffff;    
	fmt->alpha = 0xff;	  
	surface = SDL_ConvertSurface(text, fmt, 0);	
	if (NULL == surface)
	{
		printf("SDL_ConvertSurface get text error\n");		
		free(fmt);
		fmt = NULL;
		return NULL;
	}

	SDL_FreeSurface(text); 
	free(fmt);
	fmt = NULL;

	return surface;	
}


// hcc 海思提供的位图数据显示 sample，测试可用
S32 enc_osd_loadbmp(const char *bmp_name, BITMAP_S *pstBitmap)
{
    OSD_SURFACE_S Surface;
    OSD_BITMAPFILEHEADER bmpFileHeader;
    OSD_BITMAPINFO bmpInfo;
    U32 u32BytePerPix = 0;
     
    if(GetBmpInfo(bmp_name, &bmpFileHeader, &bmpInfo) < 0)
    {
        printf("GetBmpInfo err:%s!\n", bmp_name);
        return HI_FAILURE;
    }

    Surface.enColorFmt = OSD_COLOR_FMT_RGB1555;
    u32BytePerPix      = 2;
    
    pstBitmap->pData = malloc(u32BytePerPix * (bmpInfo.bmiHeader.biWidth) * (bmpInfo.bmiHeader.biHeight));
    
    if(NULL == pstBitmap->pData)
    {
        printf("malloc osd memroy err!\n");                                                                      
        return HI_FAILURE;
    }
	if (0 != CreateSurfaceByBitMap(bmp_name, &Surface, (HI_U8*)(pstBitmap->pData)))
    {
    	printf("file = %s open filed\n", bmp_name);
		//free(pstBitmap->pData);
		//pstBitmap->pData = HI_NULL;
		return HI_FAILURE;
	}
     
    pstBitmap->u32Width      = Surface.u16Width;
    pstBitmap->u32Height     = Surface.u16Height;
    pstBitmap->enPixelFormat = PIXEL_FORMAT_RGB_1555;

    return HI_SUCCESS;
}               

// 根据位图数据显示
S32 enc_osd_draw_bmp(const char *bmp_name, RGN_HANDLE handle)
{
	int ret;
	BITMAP_S osd_bmp;
	
	if (enc_osd_loadbmp(bmp_name, &osd_bmp))			// hcc test OK 20181207
	{
		printf("enc_osd_loadbmp error\n");
		return (-1);
	}
	//printf("bmp:: bmp w * h = %d * %d\n", osd_bmp.u32Width, osd_bmp.u32Height);
	
	ret = HI_MPI_RGN_SetBitMap(handle, &osd_bmp);
	if(ret != HI_SUCCESS) {
		printf("HI_MPI_RGN_SetBitMap failed with %#x!\n", ret);
		return HI_FAILURE;
	}
	free(osd_bmp.pData);
	
    return HI_SUCCESS;	
}

// 初始化区域，进行通道绑定，调用方法如下
// enc_osd_init_rgn_chn(&sub, NULL);
// enc_osd_init_rgn_chn(NULL, &pic);
S32 enc_osd_init_rgn_chn(enc_osd_sub *sub, enc_osd_pic *pic)
{
	int ret = 0;
	RGN_ATTR_S stRgnAttr;
	MPP_CHN_S stChn;
	RGN_CHN_ATTR_S stChnAttr;
	
	RGN_HANDLE handle;
	U32 chn;
	U32 width;
	U32 height;
	U32 pos_x;
	U32 pos_y;
	U32 u32BgAlpha;
	unsigned int u32BgColor;

	// 根据传入指针，修改相关变量，初始化对应区域和通道
	if (sub !=NULL && pic == NULL)
	{
		handle = sub->sub_handle;
		chn = sub->sub_chn;
		width = sub->sub_rgn_width + sub->sub_rgn_width % 2;	// 2字节对其
		height = sub->sub_rgn_heigh + sub->sub_rgn_heigh % 2;
		pos_x = sub->sub_x + sub->sub_x % 2;
		pos_y = sub->sub_y + sub->sub_y % 2;
		u32BgAlpha = sub->sub_rgn_bgalpha;
		u32BgColor = sub->sub_rgn_bgcolor;
	}
	else if (sub == NULL && pic != NULL)
	{
		handle = pic->pic_handle;
		chn = pic->pic_chn;
		width = pic->pic_rgn_width + pic->pic_rgn_width % 2;
		height = pic->pic_rgn_heigh + pic->pic_rgn_heigh % 2;
		pos_x = pic->pic_x + pic->pic_x % 2;
		pos_y = pic->pic_y + pic->pic_y  % 2;
		u32BgAlpha = pic->pic_rgn_bgalpha;
		u32BgColor = pic->pic_rgn_bgcolor;
	}
	else
	{
		printf("usage enc_osd_init_rgn_chn(&sub, NULL)  enc_osd_init_rgn_chn(NULL, &pic)");
		return -1;
	}
	
	stRgnAttr.enType = OVERLAY_RGN;
	stRgnAttr.unAttr.stOverlay.enPixelFmt = PIXEL_FORMAT_RGB_1555;
	stRgnAttr.unAttr.stOverlay.stSize.u32Width  = width; 
	stRgnAttr.unAttr.stOverlay.stSize.u32Height = height;
	// color 
	stRgnAttr.unAttr.stOverlay.u32BgColor = RGB_R(u32BgColor)>>3<<10 | RGB_G(u32BgColor)>>3<<5 | RGB_B(u32BgColor)>>3 | 0x8000;

	//printf("##### stRgnAttr.unAttr.stOverlay.u32BgColor = 0x%x\n", stRgnAttr.unAttr.stOverlay.u32BgColor);
	HI_MPI_RGN_Destroy(handle);
	ret = HI_MPI_RGN_Create(handle, &stRgnAttr);
	if(HI_SUCCESS != ret)
	{
	    printf("HI_MPI_RGN_Create (%d) failed with %#x!\n", handle, ret);
	    HI_MPI_RGN_Destroy(handle);
	    return HI_FAILURE;
	}

	stChn.enModId = HI_ID_VENC;
	stChn.s32DevId = 0;
	stChn.s32ChnId = chn;

	memset(&stChnAttr,0,sizeof(stChnAttr));
	stChnAttr.bShow = HI_TRUE;
	stChnAttr.enType = OVERLAY_RGN;
	stChnAttr.unChnAttr.stOverlayChn.stPoint.s32X = pos_x;
	stChnAttr.unChnAttr.stOverlayChn.stPoint.s32Y = pos_y;
	stChnAttr.unChnAttr.stOverlayChn.u32BgAlpha = u32BgAlpha;
	stChnAttr.unChnAttr.stOverlayChn.u32FgAlpha = 128;
	stChnAttr.unChnAttr.stOverlayChn.u32Layer = 4;
	stChnAttr.unChnAttr.stOverlayChn.stQpInfo.bAbsQp = HI_FALSE;
	stChnAttr.unChnAttr.stOverlayChn.stQpInfo.s32Qp  = 0;

	ret = HI_MPI_RGN_AttachToChn(handle, &stChn, &stChnAttr);
	if(HI_SUCCESS != ret)
	{
	    printf("HI_MPI_RGN_AttachToChn (%d) failed with %#x!\n", handle, ret);
	    return HI_FAILURE;
	}

	return HI_SUCCESS;
}

TTF_Font *open_ttf_file(char *font, int size)
{
	TTF_Font *tmp = TTF_OpenFont(font, size);
	if(tmp == NULL) 
	{
		printf("get font is NULL error:%s\n",TTF_GetError());
		return NULL;
	}

	return tmp;
}

void enc_osd_ms_delay(int usec)
{
    struct timeval tv;
	tv.tv_sec = 0;
    tv.tv_usec = usec * 1000;
    int err;
	
    do
	{
        err = select(0, NULL, NULL, NULL, &tv);
    }while(err < 0 && errno == EINTR);
}

void *enc_osd_sub_roll_func(void *argv, enc_osd_sub *osd_sub, char *font_bmp, char *font_show)
{
	printf("font_bmp = %s, font_show = %s\n", font_bmp, font_show);
	EncHiOSD *p_run = (EncHiOSD *)argv;
	CxImage image;
	CxImage image_tmp;
	long left, top, right, bottom; 

	left = 0;									// 左侧从哪里开始截取
	top = osd_sub->sub_font_height;			// 上面从开始，这里表示字体的高度(区域高度)
	right = osd_sub->sub_rgn_width;			// 右侧从哪里结束(区域宽度)
	bottom = 0;									// 底部从哪里结束

	printf("running enc_osd_sub_roll_func\n");

	while(left <= osd_sub->sub_font_width)
	{
		image.Load(font_bmp, CXIMAGE_FORMAT_BMP);
		if (image.IsValid())
		{
			if (true == image.Crop(left, top, right, bottom, &image_tmp))
			{
				image_tmp.IncreaseBpp(24);	
				image_tmp.Save(font_show, CXIMAGE_FORMAT_BMP);
				enc_osd_ms_delay(100);
				if (&image_tmp != NULL)
				{
					if (enc_osd_draw_bmp(font_show, osd_sub->sub_handle))
					{
						printf("enc_osd_draw_bmp error\n");
					}
				}
			}
			else
			{
				printf("bmp crop error\n");
			}
		}
		image_tmp.Destroy();
		image.Destroy();
			
		right = right + 15;	
		left = left + 15;
		
		if (left >= osd_sub->sub_font_width)
		{
			left = 0;
			right = osd_sub->sub_rgn_width;
		}	
		
		if (!p_run->running())
		{
			printf("osd enable is close, SUB exit\n");
			break;
		}
		
	}

	return (void *)(0);
}


void *enc_osd_pic_roll_show_func(void *argv, enc_osd_pic *osd_pic)
{
	EncHiOSD *p_run = (EncHiOSD *)argv;
	printf("running pic_roll_thread\n");
	int i = -1;
	stENC_OSDSET *p_osd_set = &p_run->osd_set;

	while (p_run->running())
	{
		for (i = 0; i < osd_pic->pic_num; i++)
		{
			if (p_osd_set->osd_cfg.osd_logo.logo_url[i] != NULL)
			{
				strcpy(osd_pic->pic_name, (char *)p_osd_set->osd_cfg.osd_logo.logo_url[i]);
				enc_osd_init_rgn_chn(NULL, osd_pic);	
				//printf("pic_name = %s\n", osd_pic.pic_name);
				if (enc_osd_draw_bmp(osd_pic->pic_name, osd_pic->pic_handle))
				{
					printf("enc_osd_draw_bmp error 2\n");
					return (void *)(-1);
				}
				sleep(10);
				enc_osd_destory(osd_pic->pic_chn, osd_pic->pic_handle);
				sleep(1);
			}
		}
	}

	return (void *)0;
}


int enc_osd_get_bmp_name(char *font_bmp, char*font_show)
{
	memset(font_bmp, 0, sizeof(font_bmp));
	memset(font_show, 0, sizeof(font_show));
	int aa, bb;
	aa = (int)(50.0*rand()/(RAND_MAX+1.0)) + (int)(10.0*rand()/(RAND_MAX+1.0));
	bb = (int)(50.0*rand()/(RAND_MAX+1.0)) + (int)(10.0*rand()/(RAND_MAX+1.0));
	if (aa != bb)
	while((aa = (int)(50.0*rand()/(RAND_MAX+1.0)))  != (bb = (int)(50.0*rand()/(RAND_MAX+1.0))))
	{
		sprintf(font_bmp, "%d", aa);
		strcat(font_bmp, ".bmp");
		sprintf(font_show, "%d", bb);
		strcat(font_show, ".bmp");
	}
	
	return 0;
}

int enc_osd_sub_show(void *p_this)
{
	EncHiOSD *p_run = (EncHiOSD *)p_this;
	stENC_OSDSET *p_osd_set = &p_run->osd_set;
	enc_osd_sub osd_sub;
	memset((enc_osd_sub *)&osd_sub, 0, sizeof(enc_osd_sub));
	
	char font_bmp[256];
	char font_show[256];
	enc_osd_get_bmp_name(font_bmp, font_show);
	
	printf("osd_type = BWENC_OSD_TYPE_TEXT\n");

	// 字幕显示
	osd_sub.sub_chn = 3 - g_chlidx;
	osd_sub.sub_handle = ENC_OSD_SUB_HANDLE + (int)(10.0*rand()/(RAND_MAX+1.0));

	memset((char *)osd_sub.sub_content, 0, sizeof(osd_sub.sub_content));
	memset((char *)osd_sub.sub_font, 0, sizeof(osd_sub.sub_font));
	sprintf((char *)osd_sub.sub_font, "%s", (char *)p_osd_set->osd_cfg.osd_sub.sub_font);
	sprintf((char *)osd_sub.sub_content, "%s", (char *)p_osd_set->osd_cfg.osd_sub.sub_content);
	osd_sub.sub_x = p_osd_set->osd_cfg.osd_sub.sub_x;	
	osd_sub.sub_y = p_osd_set->osd_cfg.osd_sub.sub_y;
	osd_sub.sub_rgn_width = p_osd_set->osd_cfg.osd_sub.sub_width;	
	osd_sub.sub_rgn_heigh = p_osd_set->osd_cfg.osd_sub.sub_height;

	osd_sub.sub_style = p_osd_set->osd_cfg.osd_sub.sub_fontstyle;
	osd_sub.sub_fontsize = p_osd_set->osd_cfg.osd_sub.sub_fontsize;
	osd_sub.sub_rgn_bgalpha = 128;
	osd_sub.sub_rgn_bgcolor = p_osd_set->osd_cfg.osd_sub.sub_backcolor;
	printf("bgcolor = 0x%x\n", osd_sub.sub_rgn_bgcolor);

	osd_sub.p_sub_font = open_ttf_file((char *)osd_sub.sub_font, osd_sub.sub_fontsize);			// hcc 48号 All OK 20181210		
	if (NULL == osd_sub.p_sub_font)
	{
		printf("ttf file open error, thread exit\n");
		return (-1);
	}
	// 字幕样式
	TTF_SetFontStyle(osd_sub.p_sub_font, osd_sub.sub_style);
	// 字体边缘
	//TTF_SetFontOutline(osd_sub.p_sub_font, 2);
	// 字幕间距
	//TTF_SetFontKerning(osd_sub.p_sub_font, 30);
	//enc_osd_init_rgn_chn(&osd_sub, NULL);
	SDL_Surface *surface = (SDL_Surface *)malloc(sizeof(SDL_Surface));
	if (surface == NULL)
	{
		printf("SDL_Surface malloc error\n");
		return (-1);
	}
	memset((SDL_Surface *)surface, 0, sizeof(SDL_Surface));
	surface = enc_osd_get_size(surface, (void *)p_run, &osd_sub); 	
	osd_sub.sub_font_width = surface->w;
	osd_sub.sub_font_height = surface->h;
	printf("surface->w = %d, h = %d\n", surface->w, surface->h);
	
	// 区域高度自适应
	osd_sub.sub_rgn_heigh = surface->h;
	if (osd_sub.sub_rgn_heigh % 2)		// 2字节对齐
		++osd_sub.sub_rgn_heigh;
	printf("osd_sub.sub_rgn_heigh = %d\n", osd_sub.sub_rgn_heigh);
	
	SDL_SaveBMP(surface, font_bmp);
	printf("SDL_SaveBMP OK\n");
	free(surface);
	
	enc_osd_destory(osd_sub.sub_chn, osd_sub.sub_handle);
	enc_osd_init_rgn_chn(&osd_sub, NULL);

	while (p_run->running())
	{
		if (osd_sub.sub_font_width >= osd_sub.sub_rgn_width)
		{	
			enc_osd_sub_roll_func((void*) p_run, &osd_sub, font_bmp, font_show);
		}
		else
		{
			enc_osd_draw_bmp(font_bmp, osd_sub.sub_handle);	
		}
	}
	enc_osd_destory(osd_sub.sub_chn, osd_sub.sub_handle);
	
	return 0;
}


int enc_osd_logo_show(void *p_this)
{
	EncHiOSD *p_run = (EncHiOSD *)p_this;
	stENC_OSDSET *p_osd_set = &p_run->osd_set;
	enc_osd_pic osd_pic;
	memset((enc_osd_pic *)&osd_pic, 0, sizeof(enc_osd_pic));
	
	printf("osd_type = BWENC_OSD_TYPE_LOGO\n");
			
	osd_pic.pic_chn = 3 - g_chlidx;
	osd_pic.pic_handle = ENC_OSD_LOGO_HANDLE + (int)(10.0*rand()/(RAND_MAX+1.0));

	osd_pic.pic_rgn_width = p_osd_set->osd_cfg.osd_logo.logo_width; 
	osd_pic.pic_rgn_heigh = p_osd_set->osd_cfg.osd_logo.logo_height;
	//osd_pic.pic_rgn_bgcolor = p_osd_set->osd_cfg.osd_logo.logo_rgn_bg_color;
	osd_pic.pic_rgn_bgalpha = p_osd_set->osd_cfg.osd_logo.logo_opacity;
	osd_pic.pic_x = p_osd_set->osd_cfg.osd_logo.logo_x; 
	osd_pic.pic_y = p_osd_set->osd_cfg.osd_logo.logo_y;
	osd_pic.pic_num = p_osd_set->osd_cfg.osd_logo.logo_num;
	osd_pic.pic_rgn_bgcolor = 0xABABABAB;

	while (p_run->running())
	{
		if (osd_pic.pic_num == 0)
		{
			enc_osd_init_rgn_chn(NULL, &osd_pic);
			sprintf(osd_pic.pic_name, "%s", (char *)p_osd_set->osd_cfg.osd_logo.logo_url[0]);
			printf("pic_name = %s\n", osd_pic.pic_name);

			if (enc_osd_draw_bmp(osd_pic.pic_name, osd_pic.pic_handle))
			{
				printf("enc_osd_draw_bmp error 3\n");
				return (-1);
			}
		}
		else
		{
			enc_osd_pic_roll_show_func((void *)p_run, &osd_pic);
		}

	}
	printf("PIC running disable, PIC exit\n");
	enc_osd_destory(osd_pic.pic_chn, osd_pic.pic_handle);
	return 0;
}


int enc_osd_qr_show(void *p_this)
{	
	EncHiOSD *p_run = (EncHiOSD *)p_this;
	stENC_OSDSET *p_osd_set = &p_run->osd_set;
	enc_osd_pic 	osd_qr;

	memset((enc_osd_pic *)&osd_qr, 0, sizeof(enc_osd_pic));

	printf("osd_type = BWENC_OSD_TYPE_QRCODE \n");
	osd_qr.pic_chn = 3 - g_chlidx;
	osd_qr.pic_handle = ENC_OSD_QRC_HANDLE + (int)(10.0*rand()/(RAND_MAX+1.0));

	osd_qr.pic_rgn_width = p_osd_set->osd_cfg.osd_qr.qr_width; 
	osd_qr.pic_rgn_heigh = p_osd_set->osd_cfg.osd_qr.qr_height;
	//osd_pic.pic_rgn_bgcolor = p_osd_set->osd_cfg.osd_qr.qr_rgn_bg_color;
	osd_qr.pic_rgn_bgalpha = p_osd_set->osd_cfg.osd_qr.qr_opacity;
	osd_qr.pic_x = p_osd_set->osd_cfg.osd_qr.qr_x; 
	osd_qr.pic_y = p_osd_set->osd_cfg.osd_qr.qr_y;
	osd_qr.pic_rgn_bgcolor = 0xabababab;
	sprintf((char *)osd_qr.pic_name, "%s", (char *)p_osd_set->osd_cfg.osd_qr.qr_url);

	enc_osd_init_rgn_chn(NULL, &osd_qr);	
	enc_osd_draw_bmp(osd_qr.pic_name, osd_qr.pic_handle);
	
	while(p_run->running());		// while(1) -- wait   while(0) -- break
	
	printf("QR running disable, QR exit\n");
	enc_osd_destory(osd_qr.pic_chn, osd_qr.pic_handle);
	
	return 0;
}


void hienc_start_osd()
{
	g_pOsdMgr = new HiOSDMgr();
	g_pOsdMgr->begin();
}

void hienc_stop_osd()
{
	if (g_pOsdMgr)
	{
		g_pOsdMgr->terminate();
		delete g_pOsdMgr;
		g_pOsdMgr = NULL;
	}
}

